<template>
  <div class="model-map">
    <div class="map-top">
      <el-button
        v-loading="oneKeyLoading"
        type="primary"
        size="small"
        @click="oneKeyMap"
      >
        一键映射
      </el-button>
    </div>
    <div class="map-table">
      <el-table
        :data="mapData"
        :cell-style="{ color: '#333333' }"
        :header-cell-style="{ background: '#F3F4F7', color: '#000000' }"
      >
        <el-table-column
          prop="sourceTableName"
          label="数据来源（源头表名称）"
          align="center"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          prop="targetModel"
          label="数据去向（目标模型）"
          align="center"
          show-overflow-tooltip
        >
          <template slot-scope="scope">
            <el-select
              v-model="scope.row.targetModel"
              style="width: 100%"
              filterable
              clearable
              placeholder="请选择目标模型"
            >
              <el-option
                v-for="item in targetShowModels"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              >
              </el-option>
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right" align="center">
          <template slot-scope="scope">
            <el-link
              :underline="false"
              type="primary"
              class="ontology-edit"
              @click.native.prevent="openEdit(scope.row)"
              >维护字段映射</el-link
            >
            <el-link
              :underline="false"
              type="primary"
              class="ontology-edit"
              @click.native.prevent="deleteRow(scope.$index)"
              >删除</el-link
            >
          </template>
        </el-table-column>
      </el-table>
    </div>
    <MapDialog ref="mapDialogRef" @confirm="updateMappings" />
  </div>
</template>
<script>
import MapDialog from "./modelComponents/MapDialog.vue";
export default {
  name: "ModelMap",
  components: {
    MapDialog,
  },
  props: {
    configInfo: {
      type: Object,
      default: () => {},
    },
    sourceTable: {
      type: Array,
      default: () => [],
    },
    sourceId: {
      type: [Number, String, null],
      default: null,
    },
    targetSourceId: {
      type: [Number, String, null],
      default: null,
    },
  },
  watch: {
    // 从模型映射数据中获取id
    configInfo: {
      handler(val, oldVal) {
        this.dialogForm = {
          ...this.configInfo
        }
        if (val.mappings && typeof val.mappings === "object") {
          this.finalMappings = val.mappings;
          let res = {};
          for (let k in val.mappings) {
            let item = k.split("^");
            res[item[0]] = {
              id: item[1],
              ...val.mappings[k],
            };
          }
          this.targetModelMap = res;
          this.generateData();
        }
      },
      immediate: true,
    },
    // 组装数据
    sourceTable: {
      handler(val, oldVal) {
        this.generateData();
      },
      immediate: true,
    },
  },
  data() {
    return {
      mapData: [],
      dialogForm: {},
      targetModels: [],
      targetShowModels: [],
      targetModelMap: {},
      // 最终提交的mappings
      finalMappings: {},
      // 一键映射loading
      oneKeyLoading: false,
    };
  },
  mounted() {
    this.getModelData();
  },
  methods: {
    getModelData() {
      this.$axios
        .get(this.$api.dataConnection.dataAggregation.getModelList)
        .then((res) => {
          if (res.data.code === 200) {
            this.targetModels = res.data.data.map((item) => {
              return {
                label: item.tableName + `(${item.dataSourceName})`,
                value: item.id + "",
                id: item.id,
                tableName: item.tableName,
                dataSourceId: item.dataSourceId,
              };
            });
            console.log('%c [ this.targetSourceId ]-155', 'font-size:13px; background:pink; color:#bf2c9f;', this.targetSourceId)
            this.targetShowModels = this.targetModels.filter((item) => this.targetSourceId == item.dataSourceId) 
          } else {
            this.$message.warning(res.data.message);
          }
        });
    },
    // 生成列表数据
    generateData() {
      let arr = this.sourceTable;
      if (Array.isArray(arr) && arr.length) {
        this.mapData = arr.map((item) => {
          return {
            sourceTableName: item,
            targetModel: this.targetModelMap[item]
              ? this.targetModelMap[item].id
              : null,
            isDisabled: true,
          };
        });
      }
    },
    // 一键映射
    // 遍历表格数据
    // 请求字段信息
    // 根据字段信息提取出同名映射字段
    async oneKeyMap() {
      this.oneKeyLoading = true;
      for (let i = 0; i < this.mapData.length; i++) {
        let item = this.mapData[i];
        if (item.targetModel) {
          try {
            const res = await this.$axios.post(
              this.$api.dataConnection.dataAggregation.getFieldMapInfo,
              {
                sourceDataId: this.sourceId,
                targetModelId: item.targetModel,
                sourceTableName: item.sourceTableName,
              }
            );
            const transRes = res.data.data;
            const mapFields = this.transferMap(
              transRes.sourceFieldList || [],
              transRes.targetFieldList || []
            );
            if (mapFields.length) {
              let tmpKey = `${item.sourceTableName}^${item.targetModel}`;
              this.finalMappings[tmpKey] = mapFields;
            }
          } catch {
            this.oneKeyLoading = false;
          }
        }
      }
      this.oneKeyLoading = false;
      this.$message.success("映射完成");
    },
    openEdit(row) {
      const params = {
        sourceDataId: this.sourceId,
        targetModelId: row.targetModel,
        sourceTableName: row.sourceTableName,
      };
      this.$axios
        .post(this.$api.dataConnection.dataAggregation.getFieldMapInfo, params)
        .then((res) => {
          if (res.data.code === 200) {
            let data = res.data.data;
            data.targetModelId = row.targetModel;
            const dialogRes = this.transDialogData(data);
            this.$refs.mapDialogRef.openDialog(dialogRes);
          } else {
            this.$message.warning(res.data.message);
          }
        });
    },
    // 处理映射
    transferMap(sources, targets) {
      const sourceMap = new Map();
      // 转换源头表信息
      sources.forEach((ele, index) => {
        sourceMap.set(ele.columnName, index);
      });
      // 存储结果项
      let result = [];
      targets.forEach((ele, index) => {
        if (sourceMap.has(ele.columnName)) {
          // 存在同名key时 添加到映射结果
          let sourceIdx = sourceMap.get(ele.columnName);
          result.push([sources[sourceIdx], targets[index]]);
        }
      });
      return result;
    },
    // 处理映射弹窗需要的数据
    transDialogData(res) {
      let sourceFields = res.sourceFieldList || [];
      let targetFields = res.targetFieldList || [];
      let mapKey = `${res.sourceTableName}^${res.targetModelId}`;
      let resultFields = this.finalMappings[mapKey]
        ? this.finalMappings[mapKey]
        : [];
      res.resultFieldList = resultFields;
      if (resultFields.length) {
        // 源字段
        const sourceMap = new Map();
        sourceFields.forEach((ele, index) => {
          sourceMap.set(ele.columnName, index);
        });
        // 目标模型字段
        const targetMap = new Map();
        targetFields.forEach((ele, index) => {
          targetMap.set(ele.columnName, index);
        });
        // 存储index
        let sourceIndexArr = [];
        let targetIndexArr = [];
        resultFields.forEach((f) => {
          if (sourceMap.has(f[0].columnName)) {
            sourceIndexArr.push(sourceMap.get(f[0].columnName));
          }
          if (targetMap.has(f[1].columnName)) {
            targetIndexArr.push(targetMap.get(f[1].columnName));
          }
        });
        res.sourceFieldList = res.sourceFieldList.filter(
          (e, idx) => !sourceIndexArr.includes(idx)
        );
        res.targetFieldList = res.targetFieldList.filter(
          (e, idx) => !targetIndexArr.includes(idx)
        );
      }
      return res;
    },
    // 删除行
    deleteRow(index) {
      let needRemoveList = [this.sourceTable[index]]
      needRemoveList.forEach((item) => {
        let removeId = ""
        if (this.dialogForm.cleanDataMap) {
          for (let k in this.dialogForm.cleanDataMap) {
            let table = k.split("^");
            if (table[0] == item) {
              delete this.dialogForm.cleanDataMap[k]
              removeId = table[1]
            } 
          }
        }
        if (this.dialogForm.filterDataMap) {
          for (let k in this.dialogForm.filterDataMap) {
            let table = k.split("^");
            if (table[0] == item) {
              delete this.dialogForm.filterDataMap[k]
              removeId = table[1]
            } 
          }
        }
        if (this.dialogForm.mappings) {
          for (let k in this.dialogForm.mappings) {
            let table = k.split("^");
            if (table[0] == item) {
              delete this.dialogForm.mappings[k]
              removeId = table[1]
            } 
          }
        }
      })
      this.dialogForm.sourceTableNames.splice(index, 1);
      this.mapData.splice(index, 1);
      this.sourceTable.splice(index, 1); // 删除数据源
    },
    // 更新映射数据
    updateMappings(key, res) {
      if (res.length) {
        this.finalMappings[key] = res;
      }
    },
    // 用于父组件收集数据
    getData() {
      const idArr = this.mapData.map((i) => i.targetModel);
      const res = [];
      this.targetModels.forEach((i) => {
        if (idArr.includes(i.value)) {
          res.push({ tableName: i.tableName, id: i.value });
        }
      });

      return new Promise((resolve, reject) => {
        resolve({ mappings: this.finalMappings, targetModelNames: res });
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.map-top {
  margin-bottom: 15px;
}

.ontology-edit {
  padding: 0 10px;

  & + .ontology-edit {
    border-left: 1px solid #dddddd;
  }
}
</style>
